/**
 * 
 */
package com.cmcc.pcap.jpcap.tcp.http;

import java.util.ArrayList;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.cmcc.pcap.jpcap.tcp.TcpConnection;
import com.cmcc.pcap.jpcap.tcp.TcpPacketDecorator;
import com.cmcc.pcap.jpcap.util.CommonStatistics;

/**
 * @Date 2018年5月14日 下午4:20:38
 * @author Amish
 */
public class HttpTransactionSplit {
	
	public static Logger logger = LogManager.getLogger(HttpTransactionSplit.class);
	public static String HTTP_type[] = {"CONNECT","HEAD","PUT","DELETE","POST","GET","TRACE","OPTION","PROPFIND","PROPPATCH",
										"MKCOL","COPY","MOVE","LOCK","UNLOCK","PATCH","BPROPFIND","BPROPPATCH","BCOPY","BDELETE",
										"BMOVE","NOTIFY","POLL","SEARCH","SUBSCRIBE","UNSUBSCRIBE","ORDERPATCH","ACL","UPDATE","MERGE"};
//	public static String HTTP_type[] = {"POST","GET"};
	public static long al_length=0;//
	public static int tcpconnect_num=0;
	public static long disorder_num=0; 
	
	public static ArrayList<HttpTransaction> split(TcpConnection tcpConnection) {
		
		ArrayList<HttpTransaction> al = new ArrayList<HttpTransaction>();
		/**
		 * TODO HTTP事务划分
		 * 
		 */
		int http_order = 0;
		int count = 0;
		al.add(new HttpTransaction(tcpConnection));//

		
		for(TcpPacketDecorator tcp_packet_decorator:tcpConnection.reassembleAl){
			boolean isHTTPRequest = false;
			//byte[] dataByte = tcp_packet_decorator.getData();
			byte[] dataByte = tcp_packet_decorator.getData(1);
			
			//如果数据包的data部分长度小于最小的http关键字长度，一定不是http请求，直接添加到当前的HttpTransaction中
			if(dataByte.length < 3){
				al.get(http_order).al_splited.add(tcp_packet_decorator);
			}
			else{
				int dataByteSub_length;
				if (dataByte.length<11){
                	dataByteSub_length = dataByte.length;
                }else{
                	dataByteSub_length = 11;
                }
				byte[] dataByteSub = new byte[dataByteSub_length];
				System.arraycopy(dataByte,0,dataByteSub,0,dataByteSub_length);
				String dt = new String(dataByteSub);
				logger.debug("src ip:"+tcp_packet_decorator.tcpPacket.src_ip+"; dst ip:"+tcp_packet_decorator.tcpPacket.dst_ip+"\ndata:"+dt);
				//判断tcpPacket的数据部分是否包含http请求的关键字，如果有，跳出循环且isHTTPRequest为true
				for(String http_type : HTTP_type){
					if(dt.contains(http_type)){
						isHTTPRequest=true;
						break;
					}
				} 
				if(isHTTPRequest){
					++count;
					//对于第一次http请求，直接添加到三次握手之后的HttpTransaction里
					if (count == 1){
						al.get(http_order).al_splited.add(tcp_packet_decorator);
							
					}else{
					//第二次及之后的http请求，先在al中添加HttpTransaction，再将数据包添加到新的HTTPTransaction
					    logger.debug("For "+al.size()+" HTTP transaction with "+al.get(http_order).al_splited.size()+" tcppacket.");
						al.add(new HttpTransaction(tcpConnection));
						++http_order;
					    al.get(http_order).al_splited.add(tcp_packet_decorator);	    
					}
				}
				else{
					//非http请求的数据包，直接添加到当前的HttpTransaction中
					al.get(http_order).al_splited.add(tcp_packet_decorator);	
				}
			}
			
		}
		
		
				
		/**
		 * TODO HTTP事务内各种统计：上下行流量统计、上下行包数统计、上下行乱序报文数统计、SYN ACK数统计
		 */
		for(int i=0;i<al.size();i++){
			al.get(i).HttpStatistics(tcpConnection);
			disorder_num+=(al.get(i).UL_Disorder_IP_Packet + al.get(i).DL_Disorder_IP_Packet);
		}
		
		CommonStatistics.getInstance().addHttpTransactionNum(al.size());
		al_length+=al.size();//这个静态变量会在多线程并发情况下计数不准
		tcpconnect_num++;
		logger.debug("Disorder tcppacket number:"+disorder_num+"the http transaction number is:"+al_length+"tcpconnection number:"+tcpconnect_num);
		return al;
		
		
		
	}
	
	//TEST
	public static ArrayList<HttpTransaction> split2(TcpConnection tcpConnection) {
		ArrayList<HttpTransaction> htAl = new ArrayList<HttpTransaction>();
		ArrayList<TcpPacketDecorator> tpdAl = tcpConnection.reassembleAl;
        ArrayList<Integer> indexs =  new ArrayList<Integer>();
        
        //找到每个HTTPRequest的索引
        for(int i=0 ; i < tpdAl.size() ; i++) {
            TcpPacketDecorator tcp_packet_decorator = tpdAl.get(i);
            byte[] dataByte = tcp_packet_decorator.getData(1);
            if(dataByte.length >0 ){
            	byte[] dataByteSub = new byte[11];
				System.arraycopy(dataByte,0,dataByteSub,0,11);
				String dt = new String(dataByteSub);
				//判断tcpPacket的数据部分是否包含http请求的关键字，如果有，跳出循环且isHTTPRequest为true
				for(String http_type : HTTP_type){
					if(dt.contains(http_type)){
						indexs.add(i);
						break;
					}
				}
			}	
        }
        logger.info("Request number is : "+indexs.size());
        
        int transactionnum=1;
        int fromIndex=0;
        for(int j=1 ;j<indexs.size() ; j++) {
        	Integer index = indexs.get(j);
        	HttpTransaction ht = new HttpTransaction(tcpConnection);
        	ht.al_splited = new ArrayList<TcpPacketDecorator>(tpdAl.subList(fromIndex, index));
        	htAl.add(ht);
        	logger.info(ht.al_splited.get(0).tcpPacket.sequence+ " --fromIndex is : " +fromIndex + ". Transaction packet size is : " + ht.al_splited.size());
        	fromIndex = index;
        }
        HttpTransaction ht = new HttpTransaction(tcpConnection);
    	ht.al_splited = new ArrayList<TcpPacketDecorator>(tpdAl.subList(fromIndex, tpdAl.size()));
    	htAl.add(ht);
    	logger.info(ht.al_splited.get(0).tcpPacket.sequence+ " --fromIndex is : " +fromIndex + ". Transaction packet size is : " + ht.al_splited.size());
    	
    	CommonStatistics.getInstance().addHttpTransactionNum(htAl.size());
    	
    	return null;
	    //return htAl;
	}

}
